<!--
 * @Author: wfl
 * @LastEditors: zdl
 * @description: tinymce文档地址 https://www.tiny.cloud/docs/tinymce/6/basic-setup/
 * @updateInfo:
 * @Date: 2022-10-31 10:00:36
 * @LastEditTime: 2023-12-07 09:41:27
-->
<script lang="ts" setup name="IkTinymce">
import axios from 'axios'
import tinymce from 'tinymce/tinymce'

import TinymceEditor from '@tinymce/tinymce-vue'
import 'tinymce/icons/default/icons'
import 'tinymce/models/dom'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/autoresize'
import 'tinymce/plugins/code'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/image'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/link'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/media'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/table'
import 'tinymce/plugins/wordcount'
import 'tinymce/themes/silver/theme'

import useSettingsStore from '@g/store/modules/settings'
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  setting: {
    type: Object,
    default: () => {}
  },
  disabled: {
    type: Boolean,
    default: false
  },
  minHeight: {
    type: Number,
    default: 250
  },
  maxHeight: {
    type: Number,
    default: 600
  },
  // 是否折叠
  collapse: {
    type: Boolean,
    default: false
  },
  // 具体查看tinymce的文档说明
  plugins: {
    type: String,
    default:
      'autolink autoresize fullscreen image insertdatetime link lists media preview table wordcount code searchreplace'
  },
  // 具体查看tinymce的文档说明
  toolbar: {
    type: String,
    default:
      'undo redo | blocks | fontfamily fontsize | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | forecolor backcolor removeformat | link image media table insertdatetime searchreplace | preview code fullscreen'
  },
  branding: {
    type: Boolean,
    default: false
  },
  menubar: {
    type: Boolean,
    default: false
  },
  // 将目标元素作为副文本渲染
  selector: {
    type: String || null,
    default: null
  },
  // 图片上传回调函数
  callback: {
    type: Function,
    default: null
  },
  // 允许的最大图片大小 MB
  size: {
    type: Number,
    default: 2
  },
  // 文件地址
  baseUrl: {
    type: String,
    default: ''
  },
  // 文件显示服务地址
  loadUrl: {
    type: String,
    default: ''
  },
  // token名称
  tokenName: {
    type: String,
    default: 'Authorization'
  }
})

const emit = defineEmits(['update:modelValue'])

const { uploadUrl, loadUrl: _loadUrl } = useHttpUrl()

const settingsStore = useSettingsStore()

const { token } = useToken() || {}

const defaultSetting = ref({
  font_size_input_default_unit: 'px',
  language_url: 'tinymce/langs/zh-Hans.js',
  language: 'zh-Hans',
  skin_url:
    settingsStore.settings.app.colorScheme === 'light'
      ? 'tinymce/skins/ui/oxide'
      : 'tinymce/skins/ui/oxide-dark',
  content_css:
    settingsStore.settings.app.colorScheme === 'light'
      ? 'tinymce/skins/content/default/content.min.css'
      : 'tinymce/skins/content/dark/content.min.css',
  min_height: props.minHeight,
  max_height: props.maxHeight,
  selector: props.selector,
  plugins: props.plugins,
  toolbar: props.toolbar,
  branding: props.branding,
  menubar: props.menubar,
  toolbar_mode: 'sliding',
  insertdatetime_formats: [
    '%Y年%m月%d日',
    '%H点%M分%S秒',
    '%Y-%m-%d',
    '%H:%M:%S'
  ],
  // images_upload_handler: (blobInfo: any) =>
  //   new Promise(resolve => {
  //     const img = `data:image/jpeg;base64,${blobInfo.base64()}`
  //     resolve(img)
  //   })
  // 图片上传
  images_upload_handler: (
    blobInfo: any,
    succFun: any,
    reject: any,
    progress: any
  ) => {
    return new Promise((resolve, reject) => {
      // 自定义回调函数
      if (props.callback) {
        props.callback(blobInfo, progress).then((res: any) => {
          resolve(res)
        })
        return
      }
      // 默认处理
      if (blobInfo.blob().size / 1024 / 1024 > props.size) {
        reject(new Error(`上传错误，图片大小请控制在 ${props.size}M 以内`))
      }
      else {
        const url = props.baseUrl || uploadUrl
        if (!url) {
          reject(new Error('请传入baseUrl'))
          return
        }
        const ph = props.loadUrl || _loadUrl
        const params = new FormData()
        params.append('file', blobInfo.blob())

        const config = {
          headers: {
            'Content-Type': 'multipart/form-data',
            [props.tokenName]: token
          }
        }
        axios
          .post(url, params, config)
          .then(res => {
            if (res.data.code === 0)
              resolve(ph + res.data.data.id) // 上传成功，在成功函数里填入图片路径

            else
              reject(new Error(`HTTP Error: 上传失败${res.data.code}`))
          })
          .catch(() => {
            reject(new Error('上传出错，服务器开小差了呢'))
          })
      }
    })
  }
})

const tinyValue = ref(props.modelValue)

const completeSetting = computed(() => {
  return Object.assign(defaultSetting.value, props.setting)
})

watch(
  () => tinyValue.value,
  newValue => {
    emit('update:modelValue', newValue)
  }
)

watch(
  () => props.modelValue,
  newValue => {
    tinyValue.value = newValue
  }
)

const maxHeightstyle = computed(() => `${props.collapse ? 50 : props.maxHeight}px`)

onMounted(() => {
  tinymce.init({})
})
</script>

<template>
  <div class="editor">
    <TinymceEditor
      v-model="tinyValue"
      :init="completeSetting"
      :disabled="disabled"
    />
  </div>
</template>

<style lang="scss" scoped>
:deep(.tox-tinymce) {
  border-radius: 4px;
  max-height: v-bind(maxHeightstyle);
}
</style>
